package autosimmune.agents;

import repast.simphony.engine.schedule.ScheduledMethod;
import autosimmune.agents.cells.Cell;
import autosimmune.agents.cells.PC;
import autosimmune.agents.pathogens.Bacteria;
import autosimmune.agents.pathogens.Virus;
import autosimmune.agents.portals.LymphnodePortal;
import autosimmune.defs.CitokineNames;
import autosimmune.defs.EnvParameters;
import autosimmune.env.Environment;
import autosimmune.env.Global;
import autosimmune.utils.Affinity;
import autosimmune.utils.Pattern;

/**
 * Classe que representa uma molécula de anticorpo
 * @author root
 *
 */
public class Antibody extends Antigen {

	private Pattern target;
	
	private int duration;
	
	private Cell bindcell = null;
	
	private boolean especific = false;
	
	private boolean calculedEspecific = false;
	
	public Antibody(Environment zone, int x, int y, Pattern target) {
		super(zone, x, y, new Pattern(Global.getInstance().getStringParameter(EnvParameters.ANTIBODY_SELF_PATTERN)));
		this.target = target;
		this.duration = Global.getInstance().getIntegerParameter(EnvParameters.ANTIBODY_LIFETIME);
	}
	

	public Pattern getTarget(){
		return this.target;
	}
	
	@ScheduledMethod(start = 0, interval = 1)
	public void step() {
			
			
			randomWalk(true);
			//followCitokineByGradient(true, CitokineNames.MICENZYME);
			
			for(Bacteria b: getEspecificNeighbors(Bacteria.class, 1)){
				//if(Affinity.match(this.target, b.getPattern())){
					if(b.linkToAntibody(this)){
						break;
					}
				//}
			}
			
			duration--;
			if(duration <= 0){
				this.die();
			}
		
	}
	
	/**
	 * Função utilitária para gerar os gráficos
	 * @param p Padrão para o qual será testado se o anticorpo é específico
	 * @return true se o anticorpo é específico para o padrão passado por parâmetro
	 */
	public boolean isEspecific(Pattern p){
		if(!calculedEspecific){
			if(Affinity.match(this.target, p)){
				calculedEspecific = true;
				especific = true;
				return true;
			} else {
				calculedEspecific = true;
				especific = false;
				return false;
			}
		} else {
			return especific;
		}
	}
	
	public void clean(){
		if(this.bindcell != null){
			try{
				bindcell.apoptosis();
			} catch(Exception e){
				
			}
		}
		this.die();
	}

	public void link() {
		this.die();
	}

	
}
